// threadtest.cc 
//	Simple test case for the threads assignment.
//
//	Create two threads, and have them context switch
//	back and forth between themselves by calling Thread::Yield, 
//	to illustratethe inner workings of the thread system.
//
// Copyright (c) 1992-1993 The Regents of the University of California.
// All rights reserved.  See copyright.h for copyright notice and limitation 
// of liability and disclaimer of warranty provisions.

#include "copyright.h"
#include "system.h"

#include "dlist.h"
// 增加 extern 
extern void InsertItem(int which, DLList* list, int key);
extern void RemoveItem(int which, DLList* list, int key);
extern void PrintList(int which, DLList* list);
extern void InsertNItem(int N, DLList* list);
extern void RemoveNItem(int N, DLList* list);

// testnum is set in main.cc
int testnum = 1;
int T = 2; // thread number
int N = 4; // random 

//----------------------------------------------------------------------
// SimpleThread
// 	Loop 5 times, yielding the CPU to another ready thread 
//	each iteration.
//
//	"which" is simply a number identifying the thread, for debugging
//	purposes.
//----------------------------------------------------------------------

DLList* list = new DLList(); // the common list 

void
SimpleThread(int which)
{
    // 修改此部分代码
    // int num;

    // for (num = 0; num < 5; num++) {
	//     printf("*** thread %d looped %d times\n", which, num);
        // currentThread->Yield();
    // }
    printf("Thread %d start.\n", which);
    if(which == 0){
        InsertNItem(4, list);
        // InsertItem(which, list, 1);
        // InsertItem(which, list, 10);
        // InsertItem(which, list, 0);
        // InsertItem(which, list, 5); // 此处发生线程切换
        // // 此时转入else(which == 1)的代码
        // InsertItem(which, list, 3);
        // InsertItem(which, list, 7);

    } else { // which == 1
        RemoveNItem(4, list);
        // PrintList(which, list);
        // InsertItem(which, list, 3);
        // // currentThread->Yield();
        // PrintList(which, list);
    }
}

//----------------------------------------------------------------------
// ThreadTest1
// 	Set up a ping-pong between two threads, by forking a thread 
//	to call SimpleThread, and then calling SimpleThread ourselves.
//----------------------------------------------------------------------

void
ThreadTest1()
{
    DEBUG('t', "Entering ThreadTest1");

    Thread *t = new Thread("forked thread");
    
    // Add by Qi. 创建T个线程
    int i;
    for(i=1;i<T;i++){
        DEBUG('t', "Create Thread %d", i);
        t->Fork(SimpleThread, i);  // 线程1,2,...,T-1
    }
    SimpleThread(0);    // 线程0
}


//----------------------------------------------------------------------
// ThreadTest
// 	Invoke a test routine. 
//----------------------------------------------------------------------

void
ThreadTest()
{
    switch (testnum) {
    case 1:
	ThreadTest1();
	break;
    default:
	printf("No test specified.\n");
	break;
    }
}
